import cv2
import numpy as np


# 显示图片
def cv_show(image_name, image):
    cv2.namedWindow(image_name, cv2.WINDOW_NORMAL)
    cv2.imshow(image_name, image)
    cv2.waitKey(0)


img = cv2.imread("2x-IMG_4619.jpg", flags=0)
_, imgBin = cv2.threshold(img, 128, 255, cv2.THRESH_BINARY_INV)  # 二值化处理
imgBinInv = cv2.bitwise_not(imgBin)  # 二值图像的补集，用于构建标记图像

# 构造标记图像：
F0 = np.zeros(imgBinInv.shape, np.uint8)  # 边界为补集图像，其他的全黑
F0[:, 0] = imgBinInv[:, 0]
F0[:, -1] = imgBinInv[:, -1]
F0[0, :] = imgBinInv[0, :]
F0[-1, :] = imgBinInv[-1, :]

# 形态学重建
Flast = F0.copy()  # F(k)
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
iter = 0
while True:
    dilateF = cv2.dilate(Flast, kernel=element)  # 标记图像膨胀
    Fnew = cv2.bitwise_and(dilateF, imgBinInv)  # 以原始图像的补集作为模板约束重建
    if (Fnew == Flast).all():  # 收敛判断：F(k+1)=F(k)
        break  # 结束迭代
    else:
        Flast = Fnew.copy()  # 更新F(k)

    iter += 1  # 迭代次数加1

    if iter == 2:
        imgF1 = Fnew
    elif iter == 100:
        imgF100 = Fnew

print("iter=", iter)
imgRebuild = cv2.bitwise_not(Fnew)
cv_show('imgRebuild', imgRebuild)
